package com.micro.platform.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.ImmutableList;
import com.micro.platform.user.controller.dept.DeptDeletedRequ;
import com.micro.platform.user.controller.dept.DeptEditedRequ;
import com.micro.platform.user.controller.dept.DeptInfosResp;
import com.micro.platform.user.controller.dept.DeptNewRequ;
import com.micro.platform.starter.utils.BeanCopyUtil;
import com.micro.platform.user.entity.Dept;
import com.micro.platform.user.mapper.DeptMapper;
import com.micro.platform.user.service.DeptService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户-部门表 服务实现类
 * </p>
 *
 * @author zhouyk
 * @since 2021-12-06
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
    @Override
    public List<DeptInfosResp> listAll() {
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda().eq(Dept::getDeleted, Boolean.FALSE);
        List<Dept> list = list(deptQueryWrapper);
        List<DeptInfosResp> listResps = BeanCopyUtil.copyListProperties(list, DeptInfosResp::new);
        if(listResps == null){
            return Collections.emptyList();
        }
        return listResps;
    }

    @Override
    public Long addDept(DeptNewRequ deptNewRequ) {
        if(deptNewRequ.getPId() != null){
            Dept dept = this.getById(deptNewRequ.getPId());
            if (dept == null){
                deptNewRequ.setPId(null);
            }
        }
        Dept dept = BeanCopyUtil.copyProperties(deptNewRequ, Dept::new);
        return save(dept) ? dept.getId() : null;
    }

    @Override
    public Boolean edited(DeptEditedRequ deptEditedRequ) {
        Dept dept = BeanCopyUtil.copyProperties(deptEditedRequ, Dept::new);
        return updateById(dept);
    }

    @Override
    public Boolean deleted(DeptDeletedRequ deptDeletedRequ) {
        Long id = deptDeletedRequ.getId();
        UpdateWrapper<Dept> deptUpdateWrapper = new UpdateWrapper<>();
        deptUpdateWrapper.lambda().eq(Dept::getDeleted, Boolean.FALSE).eq(Dept::getId, id).set(Dept::getDeleted, Boolean.TRUE);
        this.update(deptUpdateWrapper);
        return deletedByPid(ImmutableList.of(id));
    }
    private Boolean deletedByPid(List<Long> pIds) {
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda().eq(Dept::getDeleted, Boolean.FALSE).in(Dept::getPId, pIds);
        List<Dept> list = this.list(deptQueryWrapper);
        List<Long> collect = list.stream().map(Dept::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(collect)){
            return Boolean.TRUE;
        }
        UpdateWrapper<Dept> deptUpdateWrapper = new UpdateWrapper<>();
        deptUpdateWrapper.lambda().eq(Dept::getDeleted, Boolean.FALSE).in(Dept::getId, collect).set(Dept::getDeleted, Boolean.TRUE);
        this.update(deptUpdateWrapper);
        deletedByPid(collect);
        return Boolean.TRUE;
    }

    @Override
    public List<Dept> getChildrenDeptsById(Long deptId) {
        ArrayList<Dept> depts = new ArrayList<>();
        buildChildrenDeptsByIds(depts, ImmutableList.of(deptId));
        return depts;
    }

    private void buildChildrenDeptsByIds(ArrayList<Dept> depts, List<Long> pids) {
        if(CollectionUtils.isEmpty(pids)){
            return;
        }
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda().eq(Dept::getDeleted, Boolean.FALSE).in(Dept::getPId, pids);
        List<Dept> list = this.list(deptQueryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return;
        }
        depts.addAll(list);
        List<Long> ids = list.stream().map(Dept::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(ids)){
            return;
        }
        buildChildrenDeptsByIds(depts, ids);
    }

}
